<?php

declare(strict_types=1);

namespace JfbQueue\Message;

use Hyperf\AsyncQueue\JobInterface;
use Hyperf\Contract\CompressInterface;
use Hyperf\Contract\UnCompressInterface;
use Hyperf\Utils\Codec\Json;
use JfbQueue\Driver\DriverInterface;
use Hyperf\Context\ApplicationContext;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Process\Annotation\Process;
use Hyperf\Process\ProcessManager;
use Hyperf\Redis\RedisFactory;
use Hyperfx\Framework\Exception\AppException;
use Hyperfx\Framework\Logger\Logx;
use Hyperfx\Utils\AppEnvUtil;
use Hyperfx\Utils\RunModeUtil;
use Psr\Container\ContainerInterface;
use Hyperf\Process\AbstractProcess;

class RedisStreamMessage implements MessageInterface {
    protected int $attempts = 1;
    protected string $id;
    
    public function __construct(protected mixed $body, protected  string $body_type = 'serialize')
    {
    }

    public function serialize(): array
    {
        return [
            'body' => serialize($this->body),
            'attempts' => $this->attempts
        ];
    }

    public static function unserialize(string $id, array $data): self
    {
        $bodyType = $data['body_type'] ?? 'serialize';
        if ('raw' === $bodyType) {
            $body = $data['body'];
        } else if ('json' === $bodyType) {
            $body = Json::decode($data['body']);
        } else if ('serialize' === $bodyType) {
            $body = unserialize($data['body']);
        } else {
            $body = $data['body'];
        }
        $obj = new self($body, $bodyType);
        $obj->setAttempts((int) $data['attempts']);
        $obj->setId($id);
        return $obj;
    }

    public function getBody()
    {
        return $this->body;
    }

    public function getBodyType(): string
    {
        return $this->body_type;
    }

    public function getAttempts(): int
    {
        return $this->attempts;
    }

    public function setAttempts(int $attempts = 1): void
    {
        $this->attempts = $attempts;
    }

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }
    
    public function setId(string $id): void
    {
        $this->id = $id;
    }
}